home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dc1 / genmisc.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  44KB  |  1,838 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  GENMISC.C
  9.  *
  10.  *    Miscellanious stuff and some of the more esoteric generation routines
  11.  *    such as -> . &lvalue [], etc...
  12.  */
  13.  
  14. #include "defs.h"
  15.  
  16. Prototype void GenCast(Exp **);
  17. Prototype void GenSizeof(Exp **);
  18. Prototype void GenAddr(Exp **);
  19. Prototype void GenInd(Exp **);
  20. Prototype void GenPreInc(Exp **);
  21. Prototype void GenPreDec(Exp **);
  22. Prototype void GenIntConst(Exp **);
  23. Prototype void GenStrConst(Exp **);
  24. Prototype void GenFltConst(Exp **);
  25. Prototype void GenVarRef(Exp **);
  26. Prototype void GenCall(Exp **);
  27. Prototype void GenCastArgs(Type *, Exp *, Exp **);
  28. Prototype void GenPosInc(Exp **);
  29. Prototype void GenPosDec(Exp **);
  30. Prototype void GenStructInd(Exp **);
  31. Prototype void GenStructElm(Exp **);
  32. Prototype void GenArray(Exp **);
  33. Prototype void GenBFExt(Exp **);
  34. Prototype void BitFieldResultExp(Exp *);
  35. Prototype void BitFieldResultType(Exp **, int);
  36.  
  37. Local void GenRegArgs(Exp *, char *, char *, ulong, char *, short);
  38. Local void SaveCopyConflictsRegArgs(Exp *, char *, char *, ulong, short);
  39. Local void FreeRegArgs(Exp *, char *);
  40. Local long GenPushArgs(Exp *);
  41. Local int  PushArgExp(Exp *);
  42. Local void InMaskPush(Exp *, char *);
  43. Local void InMaskPop(char *);
  44.  
  45. /*
  46.  *  GenCast()
  47.  */
  48.  
  49. void
  50. GenCast(pexp)
  51. Exp **pexp;
  52. {
  53.     Exp *exp = *pexp;        /*    left side exp, right side type    */
  54.     Exp *e1;
  55.  
  56.     Assert(exp->ex_Type);
  57.     if (GenPass == 0) {
  58.     if ((exp->ex_Flags & EF_ICAST) == 0) {            /*    see insert cast */
  59.         if (exp->ex_ExpL->ex_Type == NULL)
  60.         exp->ex_ExpL->ex_Type = exp->ex_Type;        /*    optimize    */
  61.         CallLeft();
  62.     }
  63.     e1 = exp->ex_ExpL;
  64.  
  65.     if (e1->ex_Stor.st_Type == ST_IntConst) {
  66.         e1->ex_Type = exp->ex_Type;
  67.         e1->ex_Stor.st_Size = e1->ex_Type->Size;
  68.  
  69.         if (exp->ex_Type->Id == TID_FLT) {
  70.         e1->ex_Stor.st_FltConst = IntToFPStr(e1->ex_Stor.st_IntConst, e1->ex_Stor.st_Flags & SF_UNSIGNED, &e1->ex_Stor.st_FltLen);
  71.         e1->ex_Type = exp->ex_Type;
  72.         e1->ex_Stor.st_Size = e1->ex_Type->Size;
  73.         e1->ex_Stor.st_Type = ST_FltConst;
  74.         e1->ex_Token = TokFltConst;
  75.         e1->ex_Func  = GenFltConst;
  76.         *pexp = e1;
  77.         return;
  78.         }
  79.  
  80.         if (e1->ex_Type->Flags & TF_UNSIGNED) {
  81.         switch(e1->ex_Type->Size) {
  82.         case 0:
  83.             e1->ex_Stor.st_UIntConst = 0;
  84.             break;
  85.         case 1:
  86.             e1->ex_Stor.st_UIntConst = (ubyte)e1->ex_Stor.st_UIntConst;
  87.             break;
  88.         case 2:
  89.             e1->ex_Stor.st_UIntConst = (uword)e1->ex_Stor.st_UIntConst;
  90.             break;
  91.         case 4:
  92.             break;
  93.         default:
  94.             Assert(0);
  95.         }
  96.         e1->ex_Stor.st_Flags |= SF_UNSIGNED;
  97.         } else {
  98.         switch(e1->ex_Type->Size) {
  99.         case 0:
  100.             e1->ex_Stor.st_IntConst = 0;
  101.             break;
  102.         case 1:
  103.             e1->ex_Stor.st_IntConst = (char)e1->ex_Stor.st_IntConst;
  104.             break;
  105.         case 2:
  106.             e1->ex_Stor.st_IntConst = (short)e1->ex_Stor.st_IntConst;
  107.             break;
  108.         case 4:
  109.             break;
  110.         default:
  111.             yerror(exp->ex_LexIdx, EERROR_ILLEGAL_CAST);
  112.             break;
  113.         }
  114.         e1->ex_Stor.st_Flags &= ~SF_UNSIGNED;
  115.         }
  116.         *pexp = e1;
  117.         return;
  118.     }
  119.  
  120.     /*
  121.      *  Floating constant to integer
  122.      *
  123.      *  e1->ex_StrConst  e1->ex_StrLen
  124.      */
  125.  
  126.     if (e1->ex_Stor.st_Type == ST_FltConst) {
  127.         if (exp->ex_Type->Id == TID_FLT) {    /*  flt->flt no change */
  128.         *pexp = e1;
  129.         e1->ex_Type = exp->ex_Type;
  130.         return;
  131.         }
  132.         if (exp->ex_Type->Id == TID_INT) {
  133.         e1->ex_Stor.st_IntConst = FPStrToInt(e1, e1->ex_Stor.st_FltConst, e1->ex_Stor.st_FltLen);
  134.         e1->ex_Type = exp->ex_Type;
  135.         e1->ex_Stor.st_Size = e1->ex_Type->Size;
  136.         e1->ex_Stor.st_Type = ST_IntConst;
  137.         e1->ex_Token = TokIntConst;
  138.         e1->ex_Func  = GenIntConst;
  139.         if (e1->ex_Stor.st_Size == 0)    /*  cast to void    */
  140.             e1->ex_Stor.st_IntConst = 0;
  141.         *pexp = e1;
  142.  
  143.         if (exp->ex_Type->Flags & TF_UNSIGNED)
  144.             exp->ex_Stor.st_Flags |= SF_UNSIGNED;
  145.         else
  146.             exp->ex_Stor.st_Flags &= ~SF_UNSIGNED;
  147.  
  148.         return;
  149.         }
  150.     }
  151.  
  152.     /*
  153.      *  If Flt->Flt, Flt->Int, or Int->Flt conversion then
  154.      *  set EF_CALL bit.  (doesn't handle void case here)
  155.      */
  156.  
  157.     if (exp->ex_Type->Id == TID_FLT || e1->ex_Type->Id == TID_FLT) {
  158.         exp->ex_Flags |= EF_CALL;
  159.         GenFlagCallMade();
  160.     }
  161.     exp->ex_Flags |= e1->ex_Flags & EF_CALL;
  162.     } else {
  163.     Type *t = exp->ex_Type;
  164.  
  165.     e1 = exp->ex_ExpL;
  166.  
  167.     if (exp->ex_Flags & EF_RNU) {
  168.         e1->ex_Flags |= EF_RNU;
  169.         CallLeft();
  170.         return;
  171.     }
  172.  
  173.     if (e1->ex_Type->Id == TID_ARY) {
  174.         CallLeft();
  175.         if (exp->ex_Flags & (EF_PRES|EF_ASSEQ)) {
  176.         CreateUnaryResultStorage(exp, 1);
  177.         asm_lea(exp, &e1->ex_Stor, 0, &exp->ex_Stor);
  178.         } else {
  179.         FreeStorage(&e1->ex_Stor);
  180.         /* X1 */
  181.         asm_getlea(exp, &e1->ex_Stor, &exp->ex_Stor);
  182.         }
  183.         return;
  184.     }
  185.  
  186.     /*
  187.      *  Floating point conversions    fp -> int,  int -> fp
  188.      */
  189.  
  190.     if (exp->ex_Type->Id == TID_FLT || e1->ex_Type->Id == TID_FLT) {
  191.         CallLeft();
  192.         CreateUnaryResultStorage(exp, 1);
  193.  
  194.         if (exp->ex_Type->Id == TID_FLT) {
  195.         if (e1->ex_Type->Id == TID_FLT) {   /* FLT -> FLT */
  196.             asm_fptofp(exp, &e1->ex_Stor, &exp->ex_Stor);
  197.         } else {                /* INT -> FLT */
  198.             asm_inttofp(exp, &e1->ex_Stor, &exp->ex_Stor);
  199.         }
  200.         } else {        /*    FLT -> INT  (if not cast to void)   */
  201.         if (exp->ex_Stor.st_Size)
  202.             asm_fptoint(exp, &e1->ex_Stor, &exp->ex_Stor);
  203.         }
  204.  
  205.         if (exp->ex_Type->Flags & TF_UNSIGNED)
  206.         exp->ex_Stor.st_Flags |= SF_UNSIGNED;
  207.         else
  208.         exp->ex_Stor.st_Flags &= ~SF_UNSIGNED;
  209.  
  210.         return;
  211.     }
  212.  
  213.     /*
  214.      *  Bitfield Conversions
  215.      *
  216.      *  XXX Enabled 23 Dec 95, Matt Dillon, to handle case where
  217.      *  bitfield assignment occurs within expression and then must
  218.      *  be extracted out again.
  219.      */
  220.  
  221.     if (exp->ex_Type->Id == TID_INT && e1->ex_Type->Id == TID_BITFIELD) {
  222.         CallLeft();
  223.         CreateUnaryResultStorage(exp, 1);
  224.  
  225.         if (t->Flags & TF_UNSIGNED)
  226.         exp->ex_Stor.st_Flags |= SF_UNSIGNED;
  227.         else
  228.         exp->ex_Stor.st_Flags &= ~SF_UNSIGNED;
  229.  
  230.         asm_bfext(exp, &e1->ex_Stor, &exp->ex_Stor);
  231.  
  232.         return;
  233.     }
  234.  
  235.     if ((exp->ex_Flags & (EF_PRES|EF_ASSEQ)) == 0) {
  236.         if (t->Size == e1->ex_Type->Size) {
  237.         CallLeft();
  238.         FreeStorage(&e1->ex_Stor);
  239.         ReuseStorage(&e1->ex_Stor, &exp->ex_Stor);
  240.  
  241.         if (t->Flags & TF_UNSIGNED)
  242.             exp->ex_Stor.st_Flags |= SF_UNSIGNED;
  243.         else
  244.             exp->ex_Stor.st_Flags &= ~SF_UNSIGNED;
  245.  
  246.         return;
  247.         }
  248.     }
  249.  
  250.     /*
  251.      *  If storage size is the same & storage passed down from parent
  252.      *  then pass to subexp.
  253.      */
  254.  
  255.     if (t->Size == e1->ex_Type->Size && (exp->ex_Flags & EF_PRES) && (e1->ex_Flags & (EF_CRES|EF_ASSEQ)) == 0) {
  256.         e1->ex_Flags |= EF_PRES;
  257.         e1->ex_Stor = exp->ex_Stor;
  258.  
  259.         if (e1->ex_Type->Flags & TF_UNSIGNED)    /* ??? XXX */
  260.         e1->ex_Stor.st_Flags |= SF_UNSIGNED;
  261.         else
  262.         e1->ex_Stor.st_Flags &= ~SF_UNSIGNED;
  263.  
  264.         CallLeft();
  265.         return;
  266.     }
  267.  
  268.     CallLeft();
  269.  
  270.     CreateUnaryResultStorage(exp, 1);
  271.  
  272.     if (t->Flags & TF_UNSIGNED)
  273.         exp->ex_Stor.st_Flags |= SF_UNSIGNED;
  274.     else
  275.         exp->ex_Stor.st_Flags &= ~SF_UNSIGNED;
  276.  
  277.     if (exp->ex_Stor.st_Size)
  278.         asm_ext(exp, &e1->ex_Stor, &exp->ex_Stor, e1->ex_Stor.st_Flags);
  279.     }
  280. }
  281.  
  282. /*
  283.  *  Strings use a dummy CharAryType ... not a real type because its size does
  284.  *  not match the size of the string.  So we hack the only operator that will
  285.  *  ever need the size.
  286.  */
  287.  
  288. void
  289. GenSizeof(pexp)
  290. Exp **pexp;
  291. {
  292.     Exp *exp = *pexp;
  293.     Type *type;
  294.     long size;
  295.  
  296.     if (GenPass == 0) {
  297.     if (exp->ex_ExpL) {
  298.         Exp *e1;
  299.  
  300.         CallLeft();
  301.         e1 = exp->ex_ExpL;
  302.  
  303.         type = e1->ex_Type;
  304.         size = type->Size;
  305.  
  306.         if (e1->ex_Stor.st_Type == ST_StrConst) {
  307.         DelStrList(e1->ex_Stor.st_Label);
  308.         size = e1->ex_Stor.st_StrLen;
  309.         }
  310.     } else {
  311.         type = exp->ex_Type;
  312.         size = type->Size;
  313.         if (size == 0)
  314.         {
  315.         if ((type->Id == TID_STRUCT) || (type->Id == TID_UNION))
  316.             Undefined_Tag(type, NULL, exp->ex_LexIdx);
  317.         else
  318.             yerror(exp->ex_LexIdx, EERROR_SIZEOF_TYPE_0);
  319.         }
  320.     }
  321.     exp->ex_ExpL = NULL;
  322.     AllocConstStor(&exp->ex_Stor, size, &LongType);
  323.     exp->ex_Type = &LongType;
  324.     exp->ex_Stor.st_Flags |= SF_NOSA;
  325.     exp->ex_Func = GenIntConst;
  326.     exp->ex_Flags |= EF_CRES;
  327.     }
  328. }
  329.  
  330. void
  331. GenAddr(pexp)
  332. Exp **pexp;
  333. {
  334.     Exp *exp = *pexp;
  335.     Exp *e1;
  336.  
  337.     CallLeft();
  338.     e1 = exp->ex_ExpL;
  339.  
  340.     if (GenPass == 0) {
  341.     exp->ex_Flags |= e1->ex_Flags & EF_CALL;
  342.     if (e1->ex_Token == TokVarRef)
  343.         e1->ex_Var->Flags |= VF_ADDR;
  344.  
  345. #ifdef NOTDEF
  346.     if (e1->ex_Type->Id == TID_ARY) {
  347.         if (e1->ex_Stor.st_Type != ST_IntConst)    /*  no warning for offsetof()    */
  348.         yerror(e1->ex_LexIdx, EWARN_ADDR_ARRAY_REDUNDANT);
  349.         exp->ex_Type = e1->ex_Type;
  350.     } else
  351. #endif
  352.     if (e1->ex_Type->Id == TID_BITFIELD) {
  353.         yerror(e1->ex_LexIdx, EERROR_ADDR_BITFIELD_ILLEGAL);
  354.     } else {
  355.         exp->ex_Type = TypeToPtrType(e1->ex_Type);
  356.     }
  357.     exp->ex_Flags |= EF_CRES;
  358.  
  359.     /*
  360.      *  handle address of constant pointer, make it handlable as a
  361.      *  constant expression.
  362.      */
  363.  
  364.     if (e1->ex_Stor.st_Type == ST_PtrConst) {
  365.         asm_getlea(exp, &e1->ex_Stor, &exp->ex_Stor);
  366. #ifdef NOTDEF
  367.         exp->ex_Stor.st_Type = ST_IntConst;
  368.         exp->ex_Stor.st_IntConst = e1->ex_Stor.st_PtrConst;
  369. #endif
  370.         exp->ex_Stor.st_Flags |= SF_NOSA;
  371.         exp->ex_Func = GenIntConst;
  372.         exp->ex_Flags |= EF_CRES;
  373.         if (exp->ex_Type->Id == TID_ARY)
  374.         exp->ex_Stor.st_Flags |= SF_LEA;
  375.     } else if (e1->ex_Stor.st_Type == ST_IntConst) {
  376.         exp->ex_Stor = e1->ex_Stor;
  377.         exp->ex_Stor.st_Flags &= ~SF_LEA;
  378.     }
  379.     } else {
  380.     if ((exp->ex_Flags & EF_RNU) == 0) {
  381.         if (e1->ex_Type->Id == TID_ARY) {
  382.         exp->ex_Stor = e1->ex_Stor;
  383.         } else {
  384.         FreeStorage(&e1->ex_Stor);
  385.         asm_getlea(exp, &e1->ex_Stor, &exp->ex_Stor);
  386.         }
  387.     } else {
  388.         FreeStorage(&e1->ex_Stor);
  389.     }
  390.     }
  391. }
  392.  
  393. void
  394. GenInd(pexp)
  395. Exp **pexp;
  396. {
  397.     Exp *exp = *pexp;
  398.     Exp *e1;
  399.  
  400.     CallLeft();
  401.     e1 = exp->ex_ExpL;
  402.  
  403.     if (GenPass == 0) {
  404.     exp->ex_Type = e1->ex_Type;
  405.     exp->ex_Flags |= e1->ex_Flags & EF_CALL;
  406.  
  407.     if (exp->ex_Type->Id != TID_PTR && exp->ex_Type->Id != TID_ARY) {
  408.         yerror(exp->ex_LexIdx, EERROR_INDIRECTION_NOT_PTR);
  409.         return;
  410.     }
  411.     exp->ex_Type = e1->ex_Type->SubType;
  412.     /*exp->ex_Flags |= EF_CRES;*/
  413.     } else {
  414.     FreeStorage(&e1->ex_Stor);
  415.     if ((exp->ex_Flags & EF_RNU) == 0) {
  416.         asm_getind(exp, e1->ex_Type, &e1->ex_Stor, &exp->ex_Stor, -1, -1, AutoResultStorage(exp));
  417.     }
  418.     return;
  419.     }
  420. }
  421.  
  422. void
  423. GenPreInc(pexp)
  424. Exp **pexp;
  425. {
  426.     Exp *exp = *pexp;
  427.     Exp *e1;
  428.  
  429.     CallLeft();
  430.     e1 = exp->ex_ExpL;
  431.  
  432.     if (GenPass == 0) {
  433. #ifdef NOTDEF
  434.     if (e1->ex_Stor.st_Type == ST_IntConst) {
  435.         e1->ex_Stor.st_IntConst = !e1->ex_Stor.st_IntConst;
  436.         e1->ex_Type = &LongType;
  437.         *pexp = e1;
  438.         return;
  439.     }
  440. #endif
  441.     exp->ex_Type = e1->ex_Type;
  442.     exp->ex_Flags |= e1->ex_Flags & EF_CALL;
  443.     exp->ex_Flags |= EF_CRES;
  444.  
  445.     if (e1->ex_Token == TokVarRef)
  446.         e1->ex_Var->RegFlags |= RF_MODIFIED;
  447.     if (e1->ex_Type->Id == TID_FLT) {
  448.         exp->ex_Flags |= EF_CALL;
  449.         GenFlagCallMade();
  450.     }
  451.     } else {
  452.     Stor con;
  453.  
  454.     if (exp->ex_Type->Id == TID_FLT) {
  455.         AllocFltConstStor(&con, "1", 1, exp->ex_Type);
  456.         asm_fpadd(exp, exp->ex_Type, &con, &e1->ex_Stor, &e1->ex_Stor);
  457.     } else {
  458.         AllocConstStor(&con, AutoIncDecSize(e1), e1->ex_Type);
  459.         asm_add(exp, &con, &e1->ex_Stor, &e1->ex_Stor);
  460.     }
  461.     FreeStorage(&e1->ex_Stor);
  462.  
  463.     if ((exp->ex_Flags & EF_RNU) == 0)
  464.         ReuseStorage(&e1->ex_Stor, &exp->ex_Stor);
  465.     }
  466. }
  467.  
  468. void
  469. GenPreDec(pexp)
  470. Exp **pexp;
  471. {
  472.     Exp *exp = *pexp;
  473.     Exp *e1;
  474.  
  475.     CallLeft();
  476.     e1 = exp->ex_ExpL;
  477.  
  478.     if (GenPass == 0) {
  479. #ifdef NOTDEF
  480.     if (e1->ex_Stor.st_Type == ST_IntConst) {
  481.         e1->ex_Stor.st_IntConst = !e1->ex_Stor.st_IntConst;
  482.         e1->ex_Type = &LongType;
  483.         *pexp = e1;
  484.         return;
  485.     }
  486. #endif
  487.     exp->ex_Type = e1->ex_Type;
  488.     exp->ex_Flags |= e1->ex_Flags & EF_CALL;
  489.     exp->ex_Flags |= EF_CRES;
  490.  
  491.     if (e1->ex_Token == TokVarRef)
  492.         e1->ex_Var->RegFlags |= RF_MODIFIED;
  493.     if (e1->ex_Type->Id == TID_FLT) {
  494.         exp->ex_Flags |= EF_CALL;
  495.         GenFlagCallMade();
  496.     }
  497.     } else {
  498.     Stor con;
  499.  
  500.     if (exp->ex_Type->Id == TID_FLT) {
  501.         AllocFltConstStor(&con, "1", 1, exp->ex_Type);
  502.         asm_fpsub(exp, exp->ex_Type, &e1->ex_Stor, &con, &e1->ex_Stor);
  503.     } else {
  504.         AllocConstStor(&con, AutoIncDecSize(e1), e1->ex_Type);
  505.         asm_sub(exp, &e1->ex_Stor, &con, &e1->ex_Stor);
  506.     }
  507.     FreeStorage(&e1->ex_Stor);
  508.  
  509.     if ((exp->ex_Flags & EF_RNU) == 0)
  510.         ReuseStorage(&e1->ex_Stor, &exp->ex_Stor);
  511.     }
  512. }
  513.  
  514. /*
  515.  *  GenIntConst()
  516.  */
  517.  
  518. void
  519. GenIntConst(pexp)
  520. Exp **pexp;
  521. {
  522.     Exp *exp = *pexp;
  523.  
  524.     if (GenPass == 0) {
  525.     Type *type;
  526.     long value = exp->ex_Stor.st_IntConst;
  527.  
  528.     if (exp->ex_Stor.st_Flags & SF_UNSIGNED) {
  529.         type = &ULongType;
  530.  
  531.         if ((unsigned long)value < 65536)
  532.         type = &UShortType;
  533.         if ((unsigned long)value < 256)
  534.         type = &UCharType;
  535.     } else {
  536.         type = &LongType;
  537.  
  538.         if (value >= -32768 && value < 32768)
  539.         type = &ShortType;
  540.         if (value >= -128 && value < 128)
  541.         type = &CharType;
  542.     }
  543.  
  544.  
  545.     exp->ex_Type = type;
  546.     exp->ex_Flags |= EF_CRES;
  547.     AllocConstStor(&exp->ex_Stor, value, type);
  548.     } else {
  549.     exp->ex_Stor.st_Size = exp->ex_Type->Size;
  550.  
  551.     if (exp->ex_Flags & EF_COND) {
  552.         exp->ex_Flags |= EF_CONDACK;
  553.         if (exp->ex_Cond >= 0 && exp->ex_Stor.st_IntConst)
  554.         asm_branch(exp->ex_LabelT);
  555.         if (exp->ex_Cond < 0  && !exp->ex_Stor.st_IntConst)
  556.         asm_branch(exp->ex_LabelF);
  557.     }
  558.     if (exp->ex_Type->Flags & TF_UNSIGNED)
  559.         exp->ex_Stor.st_Flags |= SF_UNSIGNED;
  560.     else
  561.         exp->ex_Stor.st_Flags &= ~SF_UNSIGNED;
  562.     }
  563. }
  564.  
  565. void
  566. GenStrConst(pexp)
  567. Exp **pexp;
  568. {
  569.     Exp *exp = *pexp;
  570.     long l;
  571.  
  572.     if (GenPass == 0) {
  573.     long iidx = -1;        /* internationalization index */
  574.     l = AllocLabel();
  575.  
  576.     exp->ex_Flags |= EF_CRES;
  577.  
  578. #ifdef COMMERCIAL
  579.     iidx = Internationalize(exp->ex_StrConst, exp->ex_StrLen);
  580. #endif
  581.     AddStrList(exp->ex_StrConst, exp->ex_StrLen, l, iidx);
  582. #ifdef COMMERCIAL
  583.     if (iidx >= 0) {
  584.         l = -l;
  585.         exp->ex_Type = &CharPtrType;
  586.     } else
  587. #endif
  588.     {
  589.         exp->ex_Type = &CharAryType;
  590.     }
  591.  
  592.     exp->ex_Stor.st_StrConst = exp->ex_StrConst;
  593.     exp->ex_Stor.st_StrLen     = exp->ex_StrLen;
  594.     exp->ex_Stor.st_Type = ST_StrConst;
  595.     exp->ex_Stor.st_Flags = SF_NOSA;
  596.     exp->ex_Stor.st_Label = l;
  597.     } else {
  598. #ifdef COMMERCIAL
  599.     if (exp->ex_Stor.st_Label < 0) {
  600.         exp->ex_Stor.st_Label = -exp->ex_Stor.st_Label;
  601.         exp->ex_Stor.st_Flags= 0;
  602.         exp->ex_Stor.st_Type = ST_RelLabel;
  603.     } else
  604. #endif
  605.     {
  606.         exp->ex_Stor.st_Flags= SF_LEA;
  607.         exp->ex_Stor.st_Type = ST_RelLabel;
  608.  
  609.         if (ConstCode)
  610.         exp->ex_Stor.st_Flags |= SF_CODE;   /*    in code section */
  611.     }
  612.     exp->ex_Stor.st_Size = PTR_SIZE;
  613.     exp->ex_Stor.st_Offset = 0;
  614.     }
  615. }
  616.  
  617. void
  618. GenFltConst(pexp)
  619. Exp **pexp;
  620. {
  621.     Exp *exp = *pexp;
  622.  
  623.     if (GenPass == 0) {
  624.     Assert(exp->ex_Type);
  625.     exp->ex_Flags |= EF_CRES;
  626.     AllocFltConstStor(&exp->ex_Stor, exp->ex_Stor.st_FltConst, exp->ex_Stor.st_FltLen, exp->ex_Type);
  627.     } else {
  628.     exp->ex_Stor.st_Size = exp->ex_Type->Size;
  629.  
  630.     if (exp->ex_Flags & EF_COND) {
  631.         exp->ex_Flags |= EF_CONDACK;
  632.         if (exp->ex_Cond >= 0 && FltIsZero(exp, exp->ex_Stor.st_FltConst, exp->ex_Stor.st_FltLen))
  633.         asm_branch(exp->ex_LabelT);
  634.         if (exp->ex_Cond < 0  && !FltIsZero(exp, exp->ex_Stor.st_FltConst, exp->ex_Stor.st_FltLen))
  635.         asm_branch(exp->ex_LabelF);
  636.     }
  637.  
  638. #ifdef NOTDEF
  639.     /*
  640.      *  Convert an fp string constant into a memory constant and change
  641.      *  the storage type to label.
  642.      */
  643.  
  644.     asm_data_mask(0);   XXX
  645.     asm_fltconst(&exp->ex_Stor, 1);
  646.     asm_code_mask(0);   XXX
  647. #endif
  648.     }
  649. }
  650.  
  651. /*
  652.  *  left side is ex_Var, a variable.  Right side is ex_Symbol, a symbol.
  653.  *
  654.  *  For array references we return the effective address of a pointer to
  655.  *  the array.    BUT, if the array is passed as an argument we return only
  656.  *  a pointer to the array (since we can't get the eff.addr without generating
  657.  *  code).
  658.  *
  659.  *  If a register variable we have a problem... The register could have been
  660.  *  forced and reused.
  661.  *
  662.  *  __dynamic variables are automatically indirected through.
  663.  */
  664.  
  665. void
  666. GenVarRef(pexp)
  667. Exp **pexp;
  668. {
  669.     Exp *exp = *pexp;
  670.     Var *var = exp->ex_Var;
  671.  
  672.     if (GenPass == 0) {
  673.     Assert(var);
  674.  
  675.     /*
  676.      *  dynamic variables are automatically indirected
  677.      */
  678.  
  679. #ifdef DYNAMIC
  680.     if ((var->Flags & TF_DYNAMIC) && (exp->ex_Flags & EF_DYNAMIC) == 0) {
  681.         exp->ex_Flags |= EF_DYNAMIC;
  682.         InsertNot(pexp);
  683.         exp = *pexp;
  684.         exp->ex_Func = GenInd;
  685.         (*exp->ex_Func)(pexp);
  686.         return;
  687.     }
  688. #endif
  689.     exp->ex_Type = var->Type;
  690.     exp->ex_Flags |= EF_CRES;
  691.     exp->ex_Stor.st_Flags |= SF_VAR;
  692.  
  693.     if (var->Type->Id == TID_PROC)
  694.         exp->ex_Type = TypeToPtrType(var->Type);
  695.  
  696.     if (var->Type->Id == TID_ARY && (var->Flags & VF_ARG))
  697.         exp->ex_Type = TypeToPtrType(exp->ex_Type->SubType);
  698.     } else {
  699.     exp->ex_Stor = var->var_Stor;
  700.     exp->ex_Stor.st_Flags |= SF_VAR;
  701.  
  702.     /*
  703.      *  check for a change in type.  In order to modify this
  704.      *  expression's type without adding another expression node
  705.      *  the type's Id and size may not be changed (see InsertCast())
  706.      */
  707.  
  708.     if (exp->ex_Type->Flags & TF_UNSIGNED)
  709.         exp->ex_Stor.st_Flags |= SF_UNSIGNED;
  710.     else
  711.         exp->ex_Stor.st_Flags &= ~SF_UNSIGNED;
  712.  
  713.     if (var->Type->Id == TID_PROC) {
  714.         if (var->var_Stor.st_Type == ST_RelName) {
  715.         if (var->var_Stor.st_Name->Len == 6 && strncmp(var->var_Stor.st_Name->Name, "alloca", 6) == 0) {
  716.             yerror(exp->ex_LexIdx, EERROR_ALLOCA);
  717.         }
  718.         if (var->var_Stor.st_Name->Len == 12 && strncmp(var->var_Stor.st_Name->Name, "_dice_alloca", 12) == 0) {
  719.             ForceLinkFlag = 1;
  720.             puts("; FORCE LINK");
  721.         }
  722.         }
  723.     }
  724.  
  725.     /*
  726.      *  XXX - handling of registerized procedure name access
  727.      *      ('@' or '_')  -mR option. XXX
  728.      */
  729.  
  730. #ifdef NOTDEF
  731.  
  732.     if (var->Type->Flags & TF_REGCALLOK) {
  733.         if (RegCallOpt > 2 || (exp->ex_Flags & EF_DIRECT)) {
  734.         /* printf("VARFLAG = %08lx\n", var->Flags); */
  735.         if (IsRegCall(var->Flags)) {
  736.             exp->ex_Stor.st_Flags |= SF_REGARGS;
  737.             var->var_Stor.st_Flags |= SF_REGARGSUSED;
  738.         }
  739.         }
  740.     }
  741. #endif
  742.     if (var->Type->Flags & TF_REGCALL) {
  743.         exp->ex_Stor.st_Flags |= SF_REGARGS;
  744.         var->var_Stor.st_Flags |= SF_REGARGSUSED;
  745.     }
  746.  
  747.  
  748.     if (exp->ex_Stor.st_Type == 0)
  749.     {
  750.         yerror(exp->ex_LexIdx, EERROR_ILLEGAL_ASSIGNMENT);
  751.         dbprintf(("var %s has no type!", SymToString(var->Sym)));
  752.         Assert(0);
  753.     }
  754.  
  755. #ifdef NOTDEF
  756.     if ((var->Flags & TF_EXTERN) && !(var->Flags & VF_DECLD)) {
  757.         AddExternList(var);
  758.         var->Flags |= VF_DECLD;
  759.     }
  760. #endif
  761.     if ((var->Flags & VF_DECLD) == 0) {
  762.         if (var->Flags & TF_EXTERN)
  763.         AddExternList(var);
  764.         var->Flags |= VF_DECLD;
  765.     }
  766.  
  767.     exp->ex_Stor.st_Size = exp->ex_Type->Size;
  768.     if (var->Type->Id == TID_ARY) {
  769.         if (var->Flags & VF_ARG) {
  770.         exp->ex_Stor.st_Size = PTR_SIZE;
  771.         } else {
  772.         exp->ex_Stor.st_Flags |= SF_LEA;
  773.         exp->ex_Stor.st_Size = PTR_SIZE;
  774.         }
  775.     }
  776.     if (var->Type->Id == TID_PROC) {
  777.         exp->ex_Stor.st_Flags |= SF_LEA;        /*    ptr to procedure */
  778.         exp->ex_Stor.st_Size = PTR_SIZE;
  779.     }
  780.     }
  781. }
  782.  
  783. /*
  784.  *  right side of call is an expression list rather than just an expression
  785.  */
  786.  
  787. void
  788. GenCall(pexp)
  789. Exp **pexp;
  790. {
  791.     Exp *exp = *pexp;
  792.     Exp *e1;
  793.  
  794.     if (GenPass == 0) {
  795.     Exp **pe = &exp->ex_ExpR;
  796.     Exp *e2;
  797.     Exp *en;
  798.  
  799.     CallLeft();
  800.     e1 = exp->ex_ExpL;
  801.  
  802.     while ((e2 = *pe) != NULL) {
  803.         en = e2->ex_Next;
  804.  
  805.         (*e2->ex_Func)(pe);
  806.  
  807.         (*pe)->ex_Next = en;
  808.         pe = &(*pe)->ex_Next;
  809.     }
  810. #ifdef NOTDEF
  811.     if (e1->ex_Stor.st_Type == ST_IntConst) {
  812.         e1->ex_Stor.st_IntConst = !e1->ex_Stor.st_IntConst;
  813.         *pexp = e1;
  814.         return;
  815.     }
  816. #endif
  817.     {
  818.         Type *t = e1->ex_Type;
  819.  
  820.         if (t->Id == TID_PTR)
  821.         t = t->SubType;
  822.  
  823.         if (t->Id != TID_PROC) {
  824.         yerror(e1->ex_LexIdx, EERROR_LHS_NOT_PROCEDURE);
  825.         exp->ex_Type = &LongType;
  826.         } else {
  827.         exp->ex_Type = t->SubType;  /*    return type of proc */
  828.         if (ProtoOnlyOpt && !(t->Flags & TF_PROTOTYPE))
  829.             yerror(e1->ex_LexIdx, EERROR_UNPROTOTYPED_CALL);
  830.         }
  831.  
  832.         GenCastArgs(t, exp, &exp->ex_ExpR);
  833.     }
  834.     exp->ex_Flags |= EF_CALL;
  835.     GenFlagCallMade();
  836.     } else {
  837.     Stor *calls;
  838.     Stor ts;
  839.     short struct_ret;
  840.     PragNode *pragma_call;
  841.     Type *type = exp->ex_ExpL->ex_Type;
  842.     char prgno[16];     /*    pragma register ordering    */
  843.  
  844.     if (type->Id == TID_PTR)
  845.         type = type->SubType;
  846.     Assert(type->Id == TID_PROC);
  847.  
  848.     e1 = exp->ex_ExpL;
  849.     e1->ex_Flags |= EF_DIRECT;
  850.  
  851.     if (type->SubType->Id == TID_STRUCT || type->SubType->Id == TID_UNION)
  852.         struct_ret = 1;
  853.     else
  854.         struct_ret = 0;
  855.  
  856.     if (exp->ex_ExpL->ex_Token == TokVarRef) {
  857.         pragma_call = TestPragmaCall(exp->ex_ExpL->ex_Var, prgno);
  858.         if (pragma_call && (type->Flags & TF_PROTOTYPE) == 0)
  859.         yerror(exp->ex_LexIdx, EERROR_PROTO_REQUIRED_INLINE);
  860.     } else {
  861.         pragma_call = NULL;
  862.     }
  863.  
  864.     if (pragma_call == NULL && (type->Flags & TF_REGCALL) == 0) {
  865.         /*
  866.          *    STACK BASED CALL
  867.          */
  868.  
  869.         short autop;
  870.         long bytes;
  871.  
  872.         if (exp->ex_ExpR)
  873.         bytes = GenPushArgs(exp->ex_ExpR);
  874.         else
  875.         bytes = 0;
  876.  
  877.         if ((exp->ex_Flags & EF_STACK) && struct_ret == 0) {
  878.         exp->ex_Flags |= EF_STACKACK;
  879.         exp->ex_Flags |= EF_RNU;
  880.         autop = 1;
  881.         } else {
  882.         CreateUnaryResultStorage(exp, 0);
  883.         autop = 0;
  884.         }
  885.  
  886.         /*
  887.          *    Calculate call ea
  888.          */
  889.  
  890.         CallLeft();
  891.         e1 = exp->ex_ExpL;
  892.         calls = &e1->ex_Stor;
  893.  
  894.         FreeStorage(&e1->ex_Stor);
  895.  
  896.         if (e1->ex_Type->Id == TID_PTR) {
  897.         asm_getind(exp, e1->ex_Type, &e1->ex_Stor, &ts, -1, -1, 0);
  898.         calls = &ts;
  899.         FreeStorage(calls);
  900.         }
  901.  
  902.         /*
  903.          *    stack call, must clear SF_REGARGS so '_' label is used
  904.          */
  905.  
  906.         calls->st_Flags &= ~SF_REGARGS;
  907.  
  908.         if (exp->ex_Flags & EF_RNU)
  909.         asm_call(exp, calls, exp->ex_Type, NULL, bytes, autop);
  910.         else
  911.         asm_call(exp, calls, exp->ex_Type, &exp->ex_Stor, bytes, autop);
  912.  
  913.     } else {
  914.         /*
  915.          *    REGISTERIZED PROCEDURE CALL
  916.          *
  917.          *        (1) calculate those arguments whos register destinations
  918.          *        do not conflict directly to the appropriate
  919.          *        register destinations
  920.          *
  921.          *        (2) calculate the call address to a temporary
  922.          *
  923.          *        (3) calculate those arguments whos register destinations
  924.          *        conflict, calculate them to non-conflicting temporary
  925.          *        variables.
  926.          *
  927.          *        (4) save registers in the conflict zone
  928.          *
  929.          *        (5) move remaining temporary results to actual registers
  930.          *
  931.          *        (6) make call (do not assign result storage yet)
  932.          *
  933.          *        (7) restore registers in the conflict zone, move result
  934.          *        storage elsewhere if it conflicts.
  935.          *
  936.          *        (8) assign result storage
  937.          */
  938.  
  939.         ulong conMask;    /*  conflict mask             */
  940.         ulong ignMask = -1; /*  conflict save/restore mask         */
  941.         char argno[16];    /*  procedure call register ordering */
  942.         char actno[16];    /*  actual regs for initial arg load */
  943.         char scReg[5];    /*  scratch registers saved         */
  944.         Stor res;        /*  result storage backing store     */
  945.         short resBack = 0;    /*  backing store active         */
  946.  
  947.         scReg[0] = -1;
  948.  
  949.         /*
  950.          *    Generate result storage
  951.          */
  952.  
  953.         CreateUnaryResultStorage(exp, 0);
  954.  
  955.         /*
  956.          *    Generate a register list and a conflict mask.  This call
  957.          *    also sets the 'used' bit for the registers if it is not
  958.          *    already set.
  959.          */
  960.  
  961.         conMask = RegCallOrder(type, argno, (pragma_call) ? prgno : NULL);
  962.  
  963.         dbprintf((";conMask = %08lx\n", conMask));
  964.  
  965.         /*
  966.          *    Generate arguments for those bits that do not conflict with
  967.          *    anything.  The storage for these arguments will be locked.
  968.          */
  969.  
  970.         GenRegArgs(exp->ex_ExpR, argno, actno, ~conMask, scReg, 0);
  971.  
  972.         /*
  973.          *    If the result storage conflicts with a register and is
  974.          *    not register-direct then we have to assign it to temporary
  975.          *    storage first.
  976.          *
  977.          *    If it is register direct (& conflict) then we do not have
  978.          *    to assign it to temporary storage but must clear the
  979.          *    conflict bit so we do not restore over our result
  980.          *
  981.          *    Note that since the storage for the result in the case of
  982.          *    a hard conflict is allocated after non-conflicting registers
  983.          *    are allocated it will thus not conflict with anything and
  984.          *    therefore not get restored over.
  985.          */
  986.  
  987.         if (RegisterMaskConflict(&exp->ex_Stor, conMask)) {
  988.         if (exp->ex_Stor.st_Type == ST_Reg) {
  989.             ignMask = ~(1 << exp->ex_Stor.st_RegNo);
  990.         } else {
  991.             res = exp->ex_Stor;
  992.             resBack = 1;
  993.             AllocAnyRegister(&exp->ex_Stor, exp->ex_Type, NULL);
  994.         }
  995.         }
  996.  
  997.         /*
  998.          *    Generate arguments for those bits that conflict with
  999.          *    something.  Results will be written to other temporary
  1000.          *    registers or pushed onto the stack, and locked.
  1001.          */
  1002.  
  1003.         GenRegArgs(exp->ex_ExpR, argno, actno, conMask & ignMask, scReg, 1);
  1004.  
  1005.         /*
  1006.          *    Generate call address to non-conflicting temporary
  1007.          *
  1008.          *    If the call is a __libcall we offset it by the first
  1009.          *    argument.
  1010.          *
  1011.          *    Otheriwse,
  1012.          *
  1013.          *    If the call address is a pointer we have to resolve it,
  1014.          *    if the register conflicts with an argument we have to
  1015.          *    copy it to another register.
  1016.          *
  1017.          *    We special case TID_PTR where the pointer is the same as
  1018.          *    the first argument in the call (the library base variable)
  1019.          *
  1020.          *    XXX call address not guarenteed to be in non-conflicting
  1021.          *    register!
  1022.          */
  1023.  
  1024.         InMaskPush(e1, scReg);
  1025.  
  1026.         CallLeft();
  1027.         e1 = exp->ex_ExpL;
  1028.         calls = &e1->ex_Stor;
  1029.  
  1030.         if (pragma_call) {
  1031.         AllocRegisterAbs(&ts, RB_A6, 4);
  1032.         ts.st_Type = ST_RelReg;
  1033.         ts.st_Offset = -pragma_call->pn_Offset;
  1034.         calls = &ts;
  1035.         } else if (RegisterMaskConflict(calls, conMask)) {
  1036.         AllocAddrRegister(&ts);
  1037.         if (e1->ex_Type->Id == TID_PTR)
  1038.             asm_move(exp, calls, &ts);
  1039.         else
  1040.             asm_lea(exp, calls, 0, &ts);
  1041.         FreeStorage(&ts);
  1042.         asm_getind(exp, &LongPtrType, &ts, &ts, -1, -1, 0);
  1043.         FreeStorage(calls);
  1044.         calls = &ts;
  1045.         } else if (e1->ex_Type->Id == TID_PTR) {
  1046.         asm_getind(e1, e1->ex_Type, &e1->ex_Stor, &ts, -1, -1, 0);
  1047.         FreeStorage(calls);
  1048.         calls = &ts;
  1049.         }
  1050.  
  1051.         /*
  1052.          *    Optimize result storage if it was a conflicting register,
  1053.          *    as well as prevent restoring over the result.  We force
  1054.          *    the argument into the conflicted register (and do this last
  1055.          *    so there will be no further access to the now destructed
  1056.          *    register)
  1057.          */
  1058.  
  1059.         if (ignMask != -1)
  1060.         GenRegArgs(exp->ex_ExpR, argno, actno, ~ignMask, scReg, -1);
  1061.  
  1062.         /*
  1063.          *    While calculating arguments or the call address if any
  1064.          *    subexpression had made a call we had to (and did) save
  1065.          *    any allocated scratch registers we need.  We have to
  1066.          *    restore them here.
  1067.          */
  1068.  
  1069.         InMaskPop(scReg);
  1070.  
  1071.         /*
  1072.          *    Save conflicting variables and move already-generated
  1073.          *    arguments associated with said conflicts into their
  1074.          *    proper registers.  (note: since this survives the call
  1075.          *    we cannot save conflicts into scratch registers)
  1076.          *
  1077.          *    We do not save any variable that represents the result
  1078.          *    storage as this would cause the result storage to be
  1079.          *    overwritten on restore.
  1080.          */
  1081.  
  1082.         SaveCopyConflictsRegArgs(exp->ex_ExpR, argno, actno, conMask & ignMask, 0);
  1083.  
  1084.         /*
  1085.          *    Make the call
  1086.          */
  1087.  
  1088.         FreeStorage(calls);
  1089.         if (exp->ex_Flags & EF_RNU)
  1090.         asm_call(exp, calls, exp->ex_Type, NULL, 0, 2);
  1091.         else
  1092.         asm_call(exp, calls, exp->ex_Type, &exp->ex_Stor, 0, 2);
  1093.  
  1094.         /*
  1095.          *    Restore conflicted variables, either from other registers
  1096.          *    or off the stack.
  1097.          */
  1098.  
  1099.         SaveCopyConflictsRegArgs(exp->ex_ExpR, argno, actno, conMask & ignMask, 1);
  1100.  
  1101.         FreeRegArgs(exp->ex_ExpR, actno);
  1102.  
  1103.         /*
  1104.          *    If the result would have conflicted we created a temporary
  1105.          *    for it and now must store it back after all other registers
  1106.          *    have been restored.
  1107.          */
  1108.  
  1109.         if (resBack) {
  1110.         FreeStorage(&exp->ex_Stor);
  1111.         asm_move(exp, &exp->ex_Stor, &res);
  1112.         exp->ex_Stor = res;
  1113.         }
  1114.     }
  1115.     }
  1116. }
  1117.  
  1118. /*
  1119.  *  Generate arguments to registers.  If tmpOk is 1 then argument
  1120.  *  will be generated to a temporary if the associated register is
  1121.  *  not available.
  1122.  *
  1123.  *  Must handle case where char or short quantity is placed in an
  1124.  *  address register
  1125.  *
  1126.  *  Must handle pragma case where extra register in argno/actno is the
  1127.  *  base register
  1128.  *
  1129.  *  tmpOk
  1130.  *    -1    no, force register to be used even if a conflict
  1131.  *     0    no, register must be free
  1132.  *     1    yes
  1133.  */
  1134.  
  1135. void
  1136. GenRegArgs(
  1137.     Exp *exp,
  1138.     char *argno,
  1139.     char *actno,
  1140.     ulong mask,
  1141.     char *scReg,
  1142.     short tmpOk
  1143. ) {
  1144.     Stor t;
  1145.  
  1146.     for (; exp; exp = exp->ex_Next, ++argno, ++actno) {
  1147.     short rno = -1;
  1148.  
  1149.     /*
  1150.      *  Do only the requested arguments
  1151.      */
  1152.  
  1153.     if ((mask & (1 << *argno)) == 0)
  1154.         continue;
  1155.  
  1156.     /*printf(";GenRegArgs tmp = %d argno = %d RegAlloc=%08lx RegLocked=%08lx RegUsed=%08lx\n", tmpOk, *argno, RegAlloc, RegLocked, RegUsed);*/
  1157.  
  1158.     /*
  1159.      *  Attempt to optimize destination register for the subexpression,
  1160.      *  but cannot do this if the subexpression contains a call
  1161.      *  (screws up register save & restore).  Also, due to __dp calls
  1162.      *  D0 must be the last to be resolved.  XXX ???
  1163.      *
  1164.      *  Do not optimize ADDRESS REG destination if exptype size is not 4,
  1165.      *  don't think expression generation routines can handle it.
  1166.      */
  1167.  
  1168.     if (*argno < RB_ADDR || exp->ex_Type->Size == 4) {
  1169.         if ((exp->ex_Flags & (EF_CRES|EF_ASSEQ)) == 0 && !(exp->ex_Flags & EF_CALL)) {
  1170.         if (tmpOk < 0)
  1171.             rno = AllocRegisterAbs(&t, *argno, exp->ex_Type->Size);
  1172.         else
  1173.             rno = AttemptAllocRegisterAbs(&t, *argno, exp->ex_Type->Size);
  1174.         exp->ex_Stor = t;
  1175.         exp->ex_Flags |= EF_PRES;
  1176.         }
  1177.     }
  1178.  
  1179.     InMaskPush(exp, scReg);
  1180.     (*exp->ex_Func)(&exp);
  1181.  
  1182.     if ((exp->ex_Flags & EF_PRES) == 0) {
  1183.         if (((1 << *argno) & REGSCRATCH) == 0 && exp->ex_Stor.st_Type == ST_Reg && exp->ex_Stor.st_RegNo == *argno && exp->ex_Type->Size == exp->ex_Stor.st_Size) {
  1184.         rno = *argno;
  1185.         AllocRegisterAbs(&t, rno, exp->ex_Stor.st_Size);
  1186.         } else {
  1187.         FreeStorage(&exp->ex_Stor);
  1188.         if (tmpOk < 0)
  1189.             rno = AllocRegisterAbs(&t, *argno, exp->ex_Type->Size);
  1190.         else
  1191.             rno = AttemptAllocRegisterAbs(&t, *argno, exp->ex_Type->Size);
  1192.  
  1193.         /*
  1194.          *  Hack the destination register size.  Set to 2 if short
  1195.          *  or char type.  Even though we are moving 'garbage'
  1196.          *  into the high bits of the register, the type sized bits
  1197.          *  will be correct.
  1198.          */
  1199.  
  1200.         if (rno >= RB_ADDR && exp->ex_Type->Size < 4) {
  1201.             exp->ex_Stor.st_Size = 2;
  1202.             t.st_Size = 2;
  1203.         }
  1204.         asm_move_cast(exp, &exp->ex_Stor, &t);
  1205.         }
  1206.     }
  1207.     *actno = rno;
  1208.  
  1209.     /*printf(";GenRegArgs actual = %d\n", rno);*/
  1210.  
  1211.     if ((1 << rno) & REGSCRATCH) {
  1212.         short i;
  1213.         for (i = 0; i < 4 && (short)(scReg[i] & 0x7F) != rno; ++i) {
  1214.         if (scReg[i] == -1) {
  1215.             scReg[i] = rno;
  1216.             scReg[i+1] = -1;
  1217.             break;
  1218.         }
  1219.         }
  1220.     }
  1221.  
  1222.     if (tmpOk <= 0 && rno != *argno)
  1223.     {
  1224.         dbprintf(("rno alloc failed %d/%d (%d)\n", rno, *argno, tmpOk));
  1225.         Assert(0);
  1226.     }
  1227.     }
  1228. }
  1229.  
  1230. /*
  1231.  *  We have to save any scratch registers we have in use if the expression
  1232.  *  we are about to evaluate contains a call.  We do not re-save registers
  1233.  *  which have already been saved.
  1234.  */
  1235.  
  1236. void
  1237. InMaskPush(exp, scReg)
  1238. Exp *exp;
  1239. char *scReg;
  1240. {
  1241.     if (exp->ex_Flags & EF_CALL) {
  1242.     short i;
  1243.     char c;
  1244.  
  1245.     for (i = 0; i < 4 && (c = scReg[i]) != -1; ++i) {
  1246.         if ((c & 0x80) == 0) {
  1247.         scReg[i] |= 0x80;
  1248.         asm_push_mask(1 << c);
  1249.         }
  1250.     }
  1251.     }
  1252. }
  1253.  
  1254. /*
  1255.  *  Before completing the call we have to pop any registers we had saved,
  1256.  *  and must be sure to pop them in the correct order.
  1257.  */
  1258.  
  1259. void
  1260. InMaskPop(scReg)
  1261. char *scReg;
  1262. {
  1263.     short i;
  1264.     char c;
  1265.  
  1266.     for (i = 0; i < 4 && scReg[i] != -1; ++i)
  1267.     ;
  1268.     for (--i; i >= 0; --i) {
  1269.     if ((c = scReg[i]) & 0x80) {
  1270.         asm_pop_mask(1 << (c & 0x7F));
  1271.     }
  1272.     }
  1273. }
  1274.  
  1275. /*
  1276.  *  Save conflicting registers while simultaniously moving the stored
  1277.  *  temporary into the conflicting register spot.  The stored temporaries
  1278.  *  do not conflict with any of these registers.
  1279.  *
  1280.  *  Only those registers represented by <mask> might conflict and are
  1281.  *  considered.  If possible, we EXG the temporaries with the real
  1282.  *  registers.    Otherwise we store the real registers on the stack and
  1283.  *  MOVE from the temporaries.    On restore the opposite action occurs
  1284.  *
  1285.  *  Since the register(s) are already allocated we can allocate/free
  1286.  *  without actually freeing them up.
  1287.  */
  1288.  
  1289. void
  1290. SaveCopyConflictsRegArgs(
  1291.     Exp *expBase,
  1292.     char *argno,
  1293.     char *actno,
  1294.     ulong mask,
  1295.     short restore
  1296. ) {
  1297.     Stor t;
  1298.     Stor a;
  1299.     Exp *exp;
  1300.     long regMask;
  1301.     short i;
  1302.  
  1303.     for (i = regMask = 0, exp = expBase; exp; exp = exp->ex_Next, ++i) {
  1304.     if (mask & (1 << argno[i])) {
  1305.         if ((1 << actno[i]) & REGSCRATCH) {
  1306.         if (restore == 0)
  1307.             regMask |= 1 << argno[i];
  1308.         }
  1309.     }
  1310.     }
  1311.     asm_push_mask(regMask);
  1312.  
  1313.     for (i = regMask = 0, exp = expBase; exp; exp = exp->ex_Next, ++i) {
  1314.     if (mask & (1 << argno[i])) {
  1315.         AllocRegisterAbs(&t, argno[i], exp->ex_Stor.st_Size);
  1316.         AllocRegisterAbs(&a, actno[i], exp->ex_Stor.st_Size);
  1317.  
  1318.         /*
  1319.          *    AllocRegisterAbs() forces the size of an address register
  1320.          *    to 4 currently, XXX this is a hack
  1321.          */
  1322.  
  1323.         if (exp->ex_Stor.st_Size < 4) {
  1324.         t.st_Size = 2;
  1325.         a.st_Size = 2;
  1326.         }
  1327.  
  1328.         if ((1 << actno[i]) & REGSCRATCH) {
  1329.         if (restore) {
  1330.             regMask |= 1 << argno[i];
  1331.         } else {
  1332.             asm_move(exp, &a, &t);
  1333.         }
  1334.         } else {
  1335.         asm_exg(&a, &t);
  1336.         }
  1337.         FreeRegister(&a);
  1338.         FreeRegister(&t);
  1339.     }
  1340.     }
  1341.     asm_pop_mask(regMask);
  1342. }
  1343.  
  1344. /*
  1345.  *  Free registers allocated for the call arguments, clean up.    Note
  1346.  *  that if we do not properly free arguments a software error, such
  1347.  *  as 'rno alloc failed' from the level above may occur.
  1348.  */
  1349.  
  1350. void
  1351. FreeRegArgs(exp, actno)
  1352. Exp *exp;
  1353. char *actno;
  1354. {
  1355.     Stor t;
  1356.  
  1357.     for (; exp; exp = exp->ex_Next, ++actno) {
  1358.     AllocRegisterAbs(&t, *actno, exp->ex_Stor.st_Size);
  1359.     FreeStorage(&t);
  1360.     FreeStorage(&t);
  1361.     }
  1362. }
  1363.  
  1364. Local long
  1365. GenPushArgs(exp)
  1366. Exp *exp;
  1367. {
  1368.     long bytes;
  1369.  
  1370.     if (exp->ex_Next)
  1371.     bytes = GenPushArgs(exp->ex_Next);
  1372.     else
  1373.     bytes = 0;
  1374.     return(bytes + PushArgExp(exp));
  1375. }
  1376.  
  1377. int
  1378. PushArgExp(exp)
  1379. Exp *exp;
  1380. {
  1381.     exp->ex_Flags |= EF_STACK;
  1382.     (*exp->ex_Func)(&exp);
  1383.  
  1384.     if (exp->ex_Flags & EF_STACKACK) {
  1385.     return(asm_stackbytes(exp->ex_Type));
  1386.     } else {
  1387.     FreeStorage(&exp->ex_Stor);
  1388.     return(asm_push(exp, exp->ex_Type, &exp->ex_Stor));
  1389.     }
  1390. }
  1391.  
  1392. void
  1393. GenCastArgs(type, cexp, pexp)
  1394. Type *type;
  1395. Exp *cexp;
  1396. Exp **pexp;
  1397. {
  1398.     Exp *exp = *pexp;
  1399.     short i;
  1400.  
  1401.     /*
  1402.      *    if type->Args < 0 it is not a prototype, but that is ok the way
  1403.      *    our loop works.
  1404.      */
  1405.  
  1406.     dbprintf((";%d args, flags = %08lx\n", type->Args, type->Flags));
  1407.  
  1408.     for (i = 0; i < type->Args; ++i) {
  1409.     Type *vtype;
  1410.     if (exp == NULL || (exp->ex_Flags & EF_SPECIAL)) {
  1411.         yerror(cexp->ex_LexIdx, EWARN_TOO_FEW_PARAMETERS);
  1412.         break;
  1413.     }
  1414.  
  1415.     vtype = ActualPassType(type, type->Vars[i]->Type, 0);
  1416.  
  1417.     dbprintf((";arg %d size=%ld argsize=%ld use=%ld\n", i, exp->ex_Type->Size, type->Vars[i]->Type->Size, vtype->Size));
  1418.  
  1419.     if (exp->ex_Type != vtype) {
  1420.         if (exp->ex_Type->Id == TID_INT && (vtype->Id == TID_INT || (exp->ex_Stor.st_Type == ST_IntConst && exp->ex_Stor.st_IntConst == 0))) {
  1421.         InsertCast(pexp, vtype);
  1422.         } else if (CheckConversion(exp, exp->ex_Type, vtype)) {
  1423.         InsertCast(pexp, vtype);    /*    exp no longer valid */
  1424.         }
  1425.     }
  1426.  
  1427.     exp = *pexp;
  1428.     pexp = &exp->ex_Next;
  1429.     exp = *pexp;
  1430.     }
  1431.     {
  1432.     Exp *ex;
  1433.  
  1434.     for (ex = exp; ex && (ex->ex_Flags & EF_SPECIAL); ex = ex->ex_Next)
  1435.         ;
  1436.     if (ex && (type->Flags & TF_DOTDOTDOT) == 0 && type->Args >= 0)
  1437.         yerror(ex->ex_LexIdx, EWARN_TOO_MANY_PARAMETERS);
  1438.     }
  1439.  
  1440.     while (exp) {
  1441.     Type *vtype = ActualPassType(type, exp->ex_Type, 1);
  1442.  
  1443.     if (exp->ex_Type != vtype)
  1444.         InsertCast(pexp, vtype);    /*  exp no longer valid */
  1445.     exp = *pexp;
  1446.     pexp = &exp->ex_Next;
  1447.     exp = *pexp;
  1448.     }
  1449. }
  1450.  
  1451. void
  1452. GenPosInc(pexp)
  1453. Exp **pexp;
  1454. {
  1455.     Exp *exp = *pexp;
  1456.     Exp *e1;
  1457.  
  1458.     CallLeft();
  1459.     e1 = exp->ex_ExpL;
  1460.  
  1461.     if (GenPass == 0) {
  1462. #ifdef NOTDEF
  1463.     if (e1->ex_Stor.st_Type == ST_IntConst) {
  1464.         e1->ex_Stor.st_IntConst = !e1->ex_Stor.st_IntConst;
  1465.         *pexp = e1;
  1466.         return;
  1467.     }
  1468. #endif
  1469.     exp->ex_Type = e1->ex_Type;
  1470.     exp->ex_Flags |= e1->ex_Flags & EF_CALL;
  1471.  
  1472.     if (e1->ex_Token == TokVarRef)
  1473.         e1->ex_Var->RegFlags |= RF_MODIFIED;
  1474.     if (e1->ex_Type->Id == TID_FLT) {
  1475.         exp->ex_Flags |= EF_CALL;
  1476.         GenFlagCallMade();
  1477.     }
  1478.     } else {
  1479.     Stor con;
  1480.  
  1481.     if (exp->ex_Type->Id == TID_FLT)
  1482.         AllocFltConstStor(&con, "1", 1, exp->ex_Type);
  1483.     else
  1484.         AllocConstStor(&con, AutoIncDecSize(e1), e1->ex_Type);
  1485.  
  1486.     CreateUnaryResultStorage(exp, 0);
  1487.     if ((exp->ex_Flags & EF_RNU) == 0) {
  1488.         exp->ex_Stor.st_Flags |= e1->ex_Stor.st_Flags & SF_UNSIGNED;
  1489.         asm_move(exp, &e1->ex_Stor, &exp->ex_Stor);
  1490.     }
  1491.     FreeStorage(&e1->ex_Stor);
  1492.     if (exp->ex_Type->Id == TID_FLT)
  1493.         asm_fpadd(exp, exp->ex_Type, &con, &e1->ex_Stor, &e1->ex_Stor);
  1494.     else
  1495.         asm_add(exp, &con, &e1->ex_Stor, &e1->ex_Stor);
  1496.     }
  1497. }
  1498.  
  1499. void
  1500. GenPosDec(pexp)
  1501. Exp **pexp;
  1502. {
  1503.     Exp *exp = *pexp;
  1504.     Exp *e1;
  1505.  
  1506.     CallLeft();
  1507.     e1 = exp->ex_ExpL;
  1508.  
  1509.     if (GenPass == 0) {
  1510. #ifdef NOTDEF
  1511.     if (e1->ex_Stor.st_Type == ST_IntConst) {
  1512.         e1->ex_Stor.st_IntConst = !e1->ex_Stor.st_IntConst;
  1513.         *pexp = e1;
  1514.         return;
  1515.     }
  1516. #endif
  1517.     exp->ex_Flags |= e1->ex_Flags & EF_CALL;
  1518.     exp->ex_Type = e1->ex_Type;
  1519.  
  1520.     if (e1->ex_Token == TokVarRef)
  1521.         e1->ex_Var->RegFlags |= RF_MODIFIED;
  1522.     if (e1->ex_Type->Id == TID_FLT) {
  1523.         exp->ex_Flags |= EF_CALL;
  1524.         GenFlagCallMade();
  1525.     }
  1526.     } else {
  1527.     Stor con;
  1528.  
  1529.     if (exp->ex_Type->Id == TID_FLT)
  1530.         AllocFltConstStor(&con, "1", 1, exp->ex_Type);
  1531.     else
  1532.         AllocConstStor(&con, AutoIncDecSize(e1), e1->ex_Type);
  1533.  
  1534.     CreateUnaryResultStorage(exp, 0);
  1535.     if ((exp->ex_Flags & EF_RNU) == 0) {
  1536.         exp->ex_Stor.st_Flags |= e1->ex_Stor.st_Flags & SF_UNSIGNED;
  1537.         asm_move(exp, &e1->ex_Stor, &exp->ex_Stor);
  1538.     }
  1539.     FreeStorage(&e1->ex_Stor);
  1540.     if (exp->ex_Type->Id == TID_FLT)
  1541.         asm_fpsub(exp, exp->ex_Type, &e1->ex_Stor, &con, &e1->ex_Stor);
  1542.     else
  1543.         asm_sub(exp, &e1->ex_Stor, &con, &e1->ex_Stor);
  1544.     }
  1545. }
  1546.  
  1547. /*
  1548.  *  For Ind/Elm, exp->ex_Sym (right side is a symbol)
  1549.  *
  1550.  *  BITFIELD NOTE:  Only asm_getind() is guarenteed to leave the
  1551.  *            st_BOffset and st_BSize fields alone.
  1552.  */
  1553.  
  1554. void
  1555. GenStructInd(pexp)
  1556. Exp **pexp;
  1557. {
  1558.     Exp *exp = *pexp;
  1559.     Exp *e1;
  1560.     int bfo;
  1561.  
  1562.     CallLeft();
  1563.     e1 = exp->ex_ExpL;
  1564.  
  1565.     if (GenPass == 0) {
  1566.     if (e1->ex_Type->Id != TID_PTR && e1->ex_Type->Id != TID_ARY) {
  1567.         yerror(e1->ex_LexIdx, EERROR_INDIRECTION_NOT_PTR);
  1568.         exp->ex_Type = &LongType;
  1569.         return;
  1570.     }
  1571.     exp->ex_Offset = FindStructUnionElm(e1->ex_Type->SubType, exp, &bfo);
  1572.     if (exp->ex_Type == NULL)
  1573.         exp->ex_Type = &LongType;
  1574.     if (exp->ex_Type->Id == TID_BITFIELD) {
  1575.         BitFieldResultType(pexp, bfo);
  1576.         exp = *pexp;
  1577.         e1 = exp->ex_ExpL;
  1578.     } else {
  1579.         exp->ex_Stor.st_BOffset = -1;
  1580.         exp->ex_Stor.st_BSize   = -1;
  1581.     }
  1582.     /*exp->ex_Flags |= EF_CRES;*/
  1583.     exp->ex_Flags |= e1->ex_Flags & EF_CALL;
  1584.  
  1585.     /*
  1586.      *  constant pointer
  1587.      */
  1588.  
  1589.     if (exp->ex_Type->Id != TID_BITFIELD && e1->ex_Stor.st_Type == ST_IntConst) {
  1590.         if (exp->ex_Type->Id == TID_ARY) {
  1591.         e1->ex_Stor.st_Type = ST_IntConst;
  1592.         e1->ex_Stor.st_Size = PTR_SIZE;
  1593.         e1->ex_Stor.st_IntConst = e1->ex_Stor.st_IntConst + exp->ex_Offset;
  1594.         e1->ex_Stor.st_Flags |= SF_LEA | SF_UNSIGNED;
  1595.         } else {
  1596.         e1->ex_Stor.st_Type = ST_PtrConst;
  1597.         e1->ex_Stor.st_Size = exp->ex_Type->Size;
  1598.         e1->ex_Stor.st_Offset = e1->ex_Stor.st_IntConst + exp->ex_Offset;
  1599.         e1->ex_Stor.st_Flags &= ~SF_LEA;
  1600.         }
  1601.         e1->ex_Type = exp->ex_Type;
  1602.         *pexp = e1;
  1603.     }
  1604.     } else {
  1605.     Stor con;
  1606.     Stor t;
  1607.  
  1608.     FreeStorage(&e1->ex_Stor);
  1609.  
  1610.     if ((exp->ex_Flags & EF_RNU) == 0) {
  1611.         AllocConstStor(&con, exp->ex_Offset, &LongType);
  1612.         asm_getindex(exp, e1->ex_Type, &e1->ex_Stor, &con, 1, &t, 1, 0);
  1613.         FreeStorage(&t);
  1614.         if (!(exp->ex_Stor.st_Flags & SF_BITFIELD))
  1615.         exp->ex_Stor.st_BSize = -1;
  1616.         asm_getind(exp, TypeToPtrType(exp->ex_Type), &t, &exp->ex_Stor, exp->ex_Stor.st_BOffset, exp->ex_Stor.st_BSize, AutoResultStorage(exp));
  1617.  
  1618.         /*
  1619.         if (exp->ex_Stor.st_Flags & SF_BITFIELD) {
  1620.         BitFieldResultExp(exp);
  1621.         }
  1622.         */
  1623.     }
  1624.     }
  1625. }
  1626.  
  1627. void
  1628. GenStructElm(pexp)
  1629. Exp **pexp;
  1630. {
  1631.     Exp *exp = *pexp;
  1632.     Exp *e1;
  1633.     int bfo;        /*    for bitfields    */
  1634.  
  1635.     CallLeft();
  1636.     e1 = exp->ex_ExpL;
  1637.  
  1638.     if (GenPass == 0) {
  1639.     {
  1640.         Type *t = e1->ex_Type;
  1641.  
  1642.         if (t->Id != TID_STRUCT && t->Id != TID_UNION)
  1643.         yerror(e1->ex_LexIdx, EERROR_NOT_STRUCT_UNION);
  1644.  
  1645.         exp->ex_Offset = FindStructUnionElm(t, exp, &bfo);
  1646.     }
  1647.     if (exp->ex_Type == NULL)
  1648.         exp->ex_Type = &LongType;
  1649.     if (exp->ex_Type->Id == TID_BITFIELD) {
  1650.         BitFieldResultType(pexp, bfo);
  1651.         exp = *pexp;
  1652.         e1 = exp->ex_ExpL;
  1653.     } else {
  1654.         exp->ex_Stor.st_BOffset = -1;
  1655.         exp->ex_Stor.st_BSize   = -1;
  1656.     }
  1657.     /*exp->ex_Flags |= EF_CRES;*/
  1658.     exp->ex_Flags |= e1->ex_Flags & EF_CALL;
  1659.  
  1660.     /*
  1661.      *  constant pointer
  1662.      */
  1663.  
  1664.     if (exp->ex_Type->Id != TID_BITFIELD && e1->ex_Stor.st_Type == ST_IntConst) {
  1665.         if (exp->ex_Type->Id == TID_ARY) {
  1666.         e1->ex_Stor.st_Type = ST_IntConst;
  1667.         e1->ex_Stor.st_Size = PTR_SIZE;
  1668.         e1->ex_Stor.st_IntConst = e1->ex_Stor.st_IntConst + exp->ex_Offset;
  1669.         e1->ex_Stor.st_Flags |= SF_LEA | SF_UNSIGNED;
  1670.         } else {
  1671.         e1->ex_Stor.st_Type = ST_PtrConst;
  1672.         e1->ex_Stor.st_Size = exp->ex_Type->Size;
  1673.         e1->ex_Stor.st_Offset = e1->ex_Stor.st_IntConst + exp->ex_Offset;
  1674.         e1->ex_Stor.st_Flags &= ~SF_LEA;
  1675.         }
  1676.         e1->ex_Type = exp->ex_Type;
  1677.         *pexp = e1;
  1678.     }
  1679.     } else {
  1680.     Stor con;
  1681.     Stor t;
  1682.     Stor u;
  1683.  
  1684.     FreeStorage(&e1->ex_Stor);
  1685.  
  1686.     if ((exp->ex_Flags & EF_RNU) == 0) {
  1687.         AllocConstStor(&con, exp->ex_Offset, &LongType);
  1688.  
  1689.         asm_getlea(exp, &e1->ex_Stor, &t);
  1690.         FreeStorage(&t);
  1691.  
  1692.         asm_getindex(exp, TypeToPtrType(e1->ex_Type), &t, &con, 1, &u, 1, 0);
  1693.         FreeStorage(&u);
  1694.  
  1695.         if (!(exp->ex_Stor.st_Flags & SF_BITFIELD))
  1696.         exp->ex_Stor.st_BSize = -1;
  1697.         asm_getind(exp, TypeToPtrType(exp->ex_Type), &u, &exp->ex_Stor, exp->ex_Stor.st_BOffset, exp->ex_Stor.st_BSize, AutoResultStorage(exp));
  1698.         /*
  1699.         if (exp->ex_Stor.st_Flags & SF_BITFIELD) {
  1700.         BitFieldResultExp(exp);
  1701.         }
  1702.         */
  1703.     }
  1704.     }
  1705. }
  1706.  
  1707. /*
  1708.  *  Handle bitfield result types.  If this isn't the LHS of a straight
  1709.  *  assignment, the type is coerced into an integer.
  1710.  */
  1711.  
  1712. void
  1713. BitFieldResultType(pexp, bfo)
  1714. Exp **pexp;
  1715. int bfo;
  1716. {
  1717.     Exp *exp = *pexp;
  1718.  
  1719.     exp->ex_Stor.st_BOffset = bfo;
  1720.     exp->ex_Stor.st_BSize   = exp->ex_Type->Size;
  1721.     exp->ex_Stor.st_Flags |= SF_BITFIELD;
  1722.  
  1723.     /*
  1724.      *    bit field return type is an integer unless lhs of
  1725.      *    assignment.
  1726.      */
  1727.  
  1728.     if ((exp->ex_Flags & (EF_LHSASSIGN|EF_COND)) == 0) {
  1729.     InsertNot(pexp);
  1730.     exp = *pexp;
  1731.     if (exp->ex_ExpL->ex_Flags & EF_LHSASSEQ)
  1732.         exp->ex_Flags |= EF_LHSASSEQ;
  1733.     exp->ex_Func = GenBFExt;
  1734.     exp->ex_Token = TokBFExt;   /*    FOR +=, -=, etc... */
  1735.  
  1736.     if (exp->ex_ExpL->ex_Type->Flags & TF_UNSIGNED)
  1737.         exp->ex_Type = &ULongType;
  1738.     else
  1739.         exp->ex_Type = &LongType;
  1740.     }
  1741. }
  1742.  
  1743. #ifdef NOTDEF
  1744. /*
  1745.  *  BitFieldResultExp
  1746.  */
  1747.  
  1748. void
  1749. BitFieldResultExp(exp)
  1750. Exp *exp;
  1751. {
  1752.     if (exp->ex_Flags & EF_LHSASSIGN)
  1753.     return;
  1754.     if (exp->ex_Flags & EF_COND)    /*  can handle some conds.*/
  1755.     return;
  1756.     /*
  1757.      *    but otherwise must store into integer
  1758.      */
  1759.     if (exp->ex_Stor.st_Flags & SF_BITFIELD) {
  1760.     Stor st = exp->ex_Stor;
  1761.  
  1762.     FreeStorage(&exp->ex_Stor);
  1763.     CreateUnaryResultStorage(exp, 0);
  1764.     asm_bfext(exp, &st, &exp->ex_Stor);
  1765.     }
  1766. }
  1767. #endif
  1768.  
  1769. void
  1770. GenBFExt(pexp)
  1771. Exp **pexp;
  1772. {
  1773.     Exp *e1;
  1774.     Exp *exp = *pexp;
  1775.  
  1776.     CallLeft();
  1777.     e1 = exp->ex_ExpL;
  1778.  
  1779.     if (GenPass == 0) {
  1780.     ;
  1781.     } else {
  1782.     Assert(e1->ex_Stor.st_Flags & SF_BITFIELD);
  1783.     if ((exp->ex_Flags & EF_LHSASSEQ) == 0)
  1784.         FreeStorage(&e1->ex_Stor);
  1785.     CreateUnaryResultStorage(exp, 0);
  1786.     asm_bfext(exp, &e1->ex_Stor, &exp->ex_Stor);
  1787.     }
  1788. }
  1789.  
  1790.  
  1791. void
  1792. GenArray(pexp)
  1793. Exp **pexp;
  1794. {
  1795.     Exp *exp = *pexp;
  1796.     Exp *e1;
  1797.     Exp *e2;
  1798.  
  1799.     CallLeft();
  1800.     EnsureReturnStorageLeft();
  1801.     CallRight();
  1802.     e1 = exp->ex_ExpL;
  1803.     e2 = exp->ex_ExpR;
  1804.  
  1805.     if (GenPass == 0) {
  1806.     Type *t1 = e1->ex_Type;
  1807.  
  1808.     exp->ex_Flags |= /* EF_CRES |*/ ((e1->ex_Flags | e2->ex_Flags) & EF_CALL);
  1809.     if (t1->Id == TID_PTR || t1->Id == TID_ARY) {
  1810.         exp->ex_Type = t1->SubType;
  1811.  
  1812.         if (e2->ex_Stor.st_Type != ST_IntConst) {
  1813.         if (asm_mul_requires_call(t1->SubType->Size)) {
  1814.             exp->ex_Flags |= EF_CALL;
  1815.             GenFlagCallMade();
  1816.         }
  1817.         if (e2->ex_Type->Id != TID_INT)
  1818.             yerror(e2->ex_LexIdx, EERROR_EXPECTED_INT_TYPE);
  1819.         }
  1820.         return;
  1821.     }
  1822.     yerror(e1->ex_LexIdx, EERROR_INDIRECTION_NOT_PTR);
  1823.     exp->ex_Type = &VoidPtrType;
  1824.     } else {
  1825.     Stor t;
  1826.  
  1827.     FreeStorage(&e1->ex_Stor);
  1828.     FreeStorage(&e2->ex_Stor);
  1829.     if ((exp->ex_Flags & EF_RNU) == 0) {
  1830.         asm_getindex(exp, e1->ex_Type, &e1->ex_Stor, &e2->ex_Stor, exp->ex_Type->Size, &t, 1, 0);
  1831.         FreeStorage(&t);
  1832.         asm_getind(exp, e1->ex_Type, &t, &exp->ex_Stor, -1, -1, AutoResultStorage(exp));
  1833.     }
  1834.     }
  1835. }
  1836.  
  1837.  
  1838.